﻿using System;
using System.Collections.Generic;
using System.Net.Http;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
using Newtonsoft.Json;
using System.Text;
using System.Net;
using System.Linq; // 添加LINQ命名空间以使用Select扩展方法

namespace Update.Servers.LanZou {
    /// <summary>
    /// 蓝奏云直链提取工具类
    /// </summary>
    public class LanZouDirectLinkExtractor {
        private readonly HttpClient _httpClient;
        private const string UserAgent = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/132.0.0.0 Safari/537.36";

        public LanZouDirectLinkExtractor() {
            var handler = new HttpClientHandler {
                AutomaticDecompression = DecompressionMethods.GZip | DecompressionMethods.Deflate,
                CookieContainer = new CookieContainer(),
                UseCookies = true,
                AllowAutoRedirect = true,
                MaxAutomaticRedirections = 10
            };
            _httpClient = new HttpClient(handler) {
                Timeout = TimeSpan.FromSeconds(10) // 添加超时设置，10秒
            };
            _httpClient.DefaultRequestHeaders.Add("User-Agent", UserAgent);
        }

        /// <summary>
        /// 提取蓝奏云链接的直接下载地址
        /// </summary>
        /// <param name="url">蓝奏云分享链接</param>
        /// <returns>文件信息，包含直接下载链接</returns>
        public async Task<FileInfo> ExtractDirectLinkAsync(string url, HttpClient httpClient=null) {
            // 处理链接，确保使用lanzoup.com域名
            url = NormalizeUrl(url);

            // 获取分享页面内容
            string pageContent = await GetPageContentAsync(url, httpClient);

            // 检查链接是否有效
            if (pageContent.Contains("文件取消分享了")) {
                throw new Exception("文件取消分享了");
            }

            // 提取文件名和大小
            var fileInfo = ExtractFileInfo(pageContent);

            // 获取iframe链接
            string iframeLink = ExtractIframeLink(pageContent);
            string iframeUrl = $"https://www.lanzoup.com/{iframeLink}";

            // 获取iframe页面内容
            string iframeContent = await GetPageContentAsync(iframeUrl);

            // 提取下载所需参数
            var downloadParams = ExtractDownloadParams(iframeContent);

            // 获取下载信息
            var downloadInfo = await GetDownloadInfoAsync(downloadParams, url);

            // 检查下载信息状态
            if (downloadInfo.Item1 != 1) {
                throw new Exception($"获取下载链接失败: {downloadInfo.Item2}");
            }

            // 拼接下载链接
            string downloadUrl = $"{downloadInfo.Item3}/file/{downloadInfo.Item4}";

            // 获取最终直链
            string directLink = await GetFinalDirectLinkAsync(downloadUrl);

            // 如果获取失败，返回原始下载链接
            if (string.IsNullOrEmpty(directLink)) {
                directLink = downloadUrl;
            }

            // 移除可能泄露服务器IP的pid参数
            directLink = Regex.Replace(directLink, @"pid=(.*?.)&", "");

            // 设置下载链接
            fileInfo.DownloadUrl = directLink;

            return fileInfo;
        }

        /// <summary>
        /// 标准化蓝奏云链接
        /// </summary>
        private string NormalizeUrl(string url) {
            if (string.IsNullOrEmpty(url)) {
                throw new ArgumentException("请输入URL");
            }

            // 确保链接使用lanzoup.com域名
            if (url.Contains(".com/")) {
                string fileId = url.Split(new[] { ".com/" }, StringSplitOptions.None)[1];
                return $"https://www.lanzoup.com/{fileId}";
            }

            return url;
        }

        /// <summary>
        /// 获取页面内容
        /// </summary>
        private async Task<string> GetPageContentAsync(string url, HttpClient httpClient = null) {
            try {
                // 设置随机IP，模拟PHP代码中的行为
                //_httpClient.DefaultRequestHeaders.Remove("X-FORWARDED-FOR");
                //_httpClient.DefaultRequestHeaders.Remove("CLIENT-IP");
                //_httpClient.DefaultRequestHeaders.Add("X-FORWARDED-FOR", GenerateRandomIp());
                //_httpClient.DefaultRequestHeaders.Add("CLIENT-IP", GenerateRandomIp());

                if (httpClient == null) {
                    httpClient = _httpClient;
                }

                Console.WriteLine($"开始请求URL: {url}");
                var sw = System.Diagnostics.Stopwatch.StartNew();
                
                // 添加关键请求头
                var request = new HttpRequestMessage(HttpMethod.Get, url);
                request.Headers.Add("Accept", "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8");
                request.Headers.Add("Accept-Language", "zh-CN,zh;q=0.9,en;q=0.8");
                request.Headers.Add("Cache-Control", "no-cache");
                request.Headers.Add("Pragma", "no-cache");
                request.Headers.Add("Upgrade-Insecure-Requests", "1");
                
                var response = await httpClient.SendAsync(request);
                
                sw.Stop();
                Console.WriteLine($"请求完成，耗时: {sw.ElapsedMilliseconds}ms");
                
                response.EnsureSuccessStatusCode();
                return await response.Content.ReadAsStringAsync();
            } catch (TaskCanceledException ex) {
                throw new Exception($"请求超时: {ex.Message}", ex);
            } catch (HttpRequestException ex) {
                throw new Exception($"HTTP请求错误: {ex.Message}", ex);
            } catch (Exception ex) {
                throw new Exception($"获取页面内容失败: {ex.Message}", ex);
            }
        }

        /// <summary>
        /// 提取文件信息
        /// </summary>
        private FileInfo ExtractFileInfo(string pageContent) {
            var fileInfo = new FileInfo();

            // 提取文件名
            var fileNameMatch = Regex.Match(pageContent, @"style=""font-size: 30px;text-align: center;padding: 56px 0px 20px 0px;"">(.*?)</div>");
            if (!fileNameMatch.Success) {
                fileNameMatch = Regex.Match(pageContent, @"<div class=""n_box_3fn"".*?>(.*?)</div>");
            }
            if (!fileNameMatch.Success) {
                fileNameMatch = Regex.Match(pageContent, @"var filename = '(.*?)';");
            }
            if (!fileNameMatch.Success) {
                fileNameMatch = Regex.Match(pageContent, @"div class=""b""><span>(.*?)</span></div>");
            }

            fileInfo.FileName = fileNameMatch.Success ? fileNameMatch.Groups[1].Value : "未知文件名";

            // 提取文件大小
            var fileSizeMatch = Regex.Match(pageContent, @"<div class=""n_filesize"".*?>大小：(.*?)</div>");
            if (!fileSizeMatch.Success) {
                fileSizeMatch = Regex.Match(pageContent, @"<span class=""p7"">文件大小：</span>(.*?)<br>");
            }

            fileInfo.FileSize = fileSizeMatch.Success ? fileSizeMatch.Groups[1].Value : "未知大小";

            return fileInfo;
        }

        /// <summary>
        /// 提取iframe链接
        /// </summary>
        private string ExtractIframeLink(string pageContent) {
            var iframeMatch = Regex.Match(pageContent, @"\n<iframe.*?name=""[\s\S]*?""\ssrc=""/(.*?)""");
            if (!iframeMatch.Success) {
                iframeMatch = Regex.Match(pageContent, @"<iframe.*?name=""[\s\S]*?""\ssrc=""/(.*?)""");
            }

            if (!iframeMatch.Success) {
                throw new Exception("无法找到iframe链接");
            }

            return iframeMatch.Groups[1].Value;
        }

        /// <summary>
        /// 提取下载所需参数
        /// </summary>
        private Dictionary<string, string> ExtractDownloadParams(string iframeContent) {
            var parameters = new Dictionary<string, string>();

            // 提取wp_sign参数
            var wpSignMatch = Regex.Match(iframeContent, @"wp_sign = '(.*?)'");
            if (wpSignMatch.Success) {
                parameters["sign"] = wpSignMatch.Groups[1].Value;
            }

            // 提取ajaxdata参数
            var ajaxDataMatch = Regex.Match(iframeContent, @"ajaxdata = '(.*?)'");
            if (ajaxDataMatch.Success) {
                parameters["signs"] = ajaxDataMatch.Groups[1].Value;
                parameters["websignkey"] = ajaxDataMatch.Groups[1].Value;
            }

            // 提取ajaxm.php?file=参数
            var ajaxmMatch = Regex.Match(iframeContent, @"ajaxm\.php\?file=(\d{5,})");
            if (ajaxmMatch.Success) {
                parameters["ajaxfile"] = ajaxmMatch.Groups[1].Value;
            }

            return parameters;
        }

        /// <summary>
        /// 获取下载信息
        /// </summary>
        private async Task<Tuple<int, string, string, string>> GetDownloadInfoAsync(
            Dictionary<string, string> parameters, string referer)
        {
            try
            {
                // 参考PHP代码中的实现，确保请求头和参数正确
                // 创建一个新的HttpClient实例，避免共享问题
                using (var client = new HttpClient())
                {
                    // 设置必要的请求头
                    client.DefaultRequestHeaders.Add("User-Agent", UserAgent);
                    client.DefaultRequestHeaders.Add("Accept", "application/json, text/javascript, */*");
                    client.DefaultRequestHeaders.Add("Accept-Language", "zh-CN,zh;q=0.9,en;q=0.8");
                    client.DefaultRequestHeaders.Add("Referer", referer);
                    client.DefaultRequestHeaders.Add("Origin", "https://www.lanzoup.com");
                    client.DefaultRequestHeaders.Add("X-Requested-With", "XMLHttpRequest");
                    
                    // 添加随机IP头，模拟PHP代码行为
                    string randIp = GenerateRandomIp();
                    client.DefaultRequestHeaders.Add("X-FORWARDED-FOR", randIp);
                    client.DefaultRequestHeaders.Add("CLIENT-IP", randIp);
                    
                    // 构建POST表单数据
                    var postData = new Dictionary<string, string> 
                    {
                        ["action"] = "downprocess",
                        ["sign"] = parameters["sign"],
                        ["ves"] = "1"
                    };
                    
                    // 添加可选参数
                    if (parameters.ContainsKey("websignkey"))
                        postData["websignkey"] = parameters["websignkey"];
                    
                    if (parameters.ContainsKey("websign"))
                        postData["websign"] = parameters.ContainsKey("websign") ? parameters["websign"] : "";
                    
                    if (parameters.ContainsKey("signs"))
                        postData["signs"] = parameters["signs"];
                    
                    postData["kd"] = "1"; // 统一参数
                    
                    // 使用FormUrlEncodedContent
                    var content = new FormUrlEncodedContent(postData);
                    
                    // 构建URL，确保格式正确
                    var requestUri = $"https://www.lanzoup.com/ajaxm.php?file={parameters["ajaxfile"]}";
                    
                    Console.WriteLine($"POST请求: {requestUri}");
                    Console.WriteLine($"参数: {string.Join(", ", postData.Select(x => $"{x.Key}={x.Value}"))}");
                    Console.WriteLine($"Referer: {referer}");
                    
                    // 发送请求
                    var response = await client.PostAsync(requestUri, content);
                    
                    // 检查状态码
                    if (!response.IsSuccessStatusCode)
                    {
                        Console.WriteLine($"请求失败: {(int)response.StatusCode} {response.StatusCode}");
                        
                        // 尝试备用方法：使用HttpRequestMessage构建请求
                        var request = new HttpRequestMessage(HttpMethod.Post, requestUri);
                        foreach (var header in client.DefaultRequestHeaders)
                        {
                            request.Headers.TryAddWithoutValidation(header.Key, header.Value);
                        }
                        
                        request.Content = content;
                        
                        // 再次尝试发送请求
                        response = await client.SendAsync(request);
                        response.EnsureSuccessStatusCode(); // 如果还是失败，抛出异常
                    }
                    
                    // 读取响应内容
                    var responseContent = await response.Content.ReadAsStringAsync();
                    Console.WriteLine($"响应: {responseContent}");
                    
                    // 解析JSON响应
                    var downloadInfo = JsonConvert.DeserializeObject<Dictionary<string, object>>(responseContent);
                    
                    // 检查响应格式
                    if (!downloadInfo.ContainsKey("zt"))
                    {
                        throw new Exception($"响应格式错误: {responseContent}");
                    }
                    
                    int status = Convert.ToInt32(downloadInfo["zt"]);
                    string message = downloadInfo["inf"]?.ToString() ?? "未知错误";
                    string domain = downloadInfo.ContainsKey("dom") ? downloadInfo["dom"]?.ToString() ?? "" : "";
                    string url = downloadInfo.ContainsKey("url") ? downloadInfo["url"]?.ToString() ?? "" : "";
                    
                    return new Tuple<int, string, string, string>(status, message, domain, url);
                }
            }
            catch (Exception ex)
            {
                Console.WriteLine($"获取下载信息失败: {ex.Message}");
                if (ex.InnerException != null)
                {
                    Console.WriteLine($"内部异常: {ex.InnerException.Message}");
                }
                throw new Exception($"获取下载信息失败: {ex.Message}", ex);
            }
        }

        /// <summary>
        /// 获取最终直链
        /// </summary>
        private async Task<string> GetFinalDirectLinkAsync(string url) {
            try {
                // 使用新的HttpClient以避免共享问题
                using (var client = new HttpClient(new HttpClientHandler {
                    AllowAutoRedirect = false  // 最关键的设置：禁止自动重定向，以便我们能获取到重定向的位置
                }))
                {
                    // 设置必要的请求头
                    client.DefaultRequestHeaders.Add("User-Agent", UserAgent);
                    client.DefaultRequestHeaders.Add("Accept", "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8");
                    client.DefaultRequestHeaders.Add("Accept-Language", "zh-CN,zh;q=0.9,en-US;q=0.8,en;q=0.7");
                    client.DefaultRequestHeaders.Add("Cache-Control", "no-cache");
                    client.DefaultRequestHeaders.Add("Pragma", "no-cache");
                    client.DefaultRequestHeaders.Add("Upgrade-Insecure-Requests", "1");
                    
                    // 设置Referer
                    client.DefaultRequestHeaders.Add("Referer", "https://developer.lanzoug.com");
                    
                    // 添加Cookie
                    client.DefaultRequestHeaders.Add("Cookie", "down_ip=1; expires=Sat, 16-Nov-2019 11:42:54 GMT; path=/; domain=.baidupan.com");
                    
                    Console.WriteLine($"请求最终直链URL: {url}");
                    
                    // 发送请求，使用GET请求替代HEAD请求，因为有些服务器可能不正确处理HEAD
                    var response = await client.GetAsync(url);
                    
                    // 检查是否有重定向 (通常是302重定向)
                    if (response.StatusCode == HttpStatusCode.Found || 
                        response.StatusCode == HttpStatusCode.MovedPermanently || 
                        response.StatusCode == HttpStatusCode.Redirect || 
                        response.StatusCode == HttpStatusCode.TemporaryRedirect || 
                        (int)response.StatusCode == 308) // 308是PermanentRedirect，较新版本的.NET可能没有定义
                    {
                        var location = response.Headers.Location;
                        if (location != null) 
                        {
                            var redirectUrl = location.IsAbsoluteUri ? location.ToString() : 
                                new Uri(new Uri(url), location).ToString();
                                
                            Console.WriteLine($"获取到重定向地址: {redirectUrl}");
                            
                            // 修复pid参数可能导致的服务器ip地址泄露
                            redirectUrl = Regex.Replace(redirectUrl, @"pid=(.*?.)&", "");
                            
                            return redirectUrl;
                        }
                    }
                    
                    Console.WriteLine($"未找到重定向地址，状态码: {(int)response.StatusCode} {response.StatusCode}");
                    
                    // 使用备选方法：读取头部信息
                    if (response.Headers.Contains("Location"))
                    {
                        var redirectUrl = response.Headers.GetValues("Location").FirstOrDefault();
                        if (!string.IsNullOrEmpty(redirectUrl))
                        {
                            Console.WriteLine($"从头部获取到重定向地址: {redirectUrl}");
                            
                            // 修复pid参数可能导致的服务器ip地址泄露
                            redirectUrl = Regex.Replace(redirectUrl, @"pid=(.*?.)&", "");
                            
                            return redirectUrl;
                        }
                    }
                    
                    // 读取响应内容，检查是否包含重定向信息
                    var content = await response.Content.ReadAsStringAsync();
                    var metaRefreshMatch = Regex.Match(content, @"<meta[^>]+?url=([^""'>\s]+)[^>]*>");
                    if (metaRefreshMatch.Success)
                    {
                        var redirectUrl = WebUtility.HtmlDecode(metaRefreshMatch.Groups[1].Value);
                        Console.WriteLine($"从meta标签获取到重定向地址: {redirectUrl}");
                        
                        // 修复pid参数可能导致的服务器ip地址泄露
                        redirectUrl = Regex.Replace(redirectUrl, @"pid=(.*?.)&", "");
                        
                        return redirectUrl;
                    }
                    
                    return string.Empty;
                }
            } catch (Exception ex) {
                // 记录详细错误日志
                Console.WriteLine($"获取最终直链时发生错误: {ex.Message}");
                if (ex.InnerException != null)
                {
                    Console.WriteLine($"内部异常: {ex.InnerException.Message}");
                }
                
                // 如果出错，返回空字符串，后续将使用原始链接
                return string.Empty;
            }
        }

        /// <summary>
        /// 生成随机IP地址
        /// </summary>
        private string GenerateRandomIp() {
            // 模拟PHP代码中的随机IP生成逻辑
            var random = new Random();
            int ip2id = random.Next(600000, 2550000) / 10000;
            int ip3id = random.Next(600000, 2550000) / 10000;
            int ip4id = random.Next(600000, 2550000) / 10000;

            string[] ip1Array = {
                "218", "218", "66", "66", "218", "218", "60", "60", "202", "204", "66", "66",
                "66", "59", "61", "60", "222", "221", "66", "59", "60", "60", "66", "218",
                "218", "62", "63", "64", "66", "66", "122", "211"
            };

            string ip1id = ip1Array[random.Next(0, ip1Array.Length)];

            return $"{ip1id}.{ip2id}.{ip3id}.{ip4id}";
        }

        /// <summary>
        /// 文件信息类
        /// </summary>
        public class FileInfo {
            /// <summary>
            /// 文件名
            /// </summary>
            public string FileName { get; set; }

            /// <summary>
            /// 文件大小
            /// </summary>
            public string FileSize { get; set; }

            /// <summary>
            /// 下载链接
            /// </summary>
            public string DownloadUrl { get; set; }
        }
    }
}
